/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package banaanvraag.tools.tokeniser;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 *
 * @author Luc
 */
public class SimpleTokeniser {
    
    /**
     * The text that has to be tokenised
     */
    private String text;
    
    /**
     * The resulting list of Tokens
     */
    private List<Token> tokens;
    
    /**
     * All token types for this tokeniser
     */
    private List<Integer> tokenTypes;
    
    /**
     * All Patterns of Tokens for this tokeniser
     */
    private List<Pattern> tokenPatterns;
    
    private int skippedCharacters = 0;
    
    private int index = 0;
    
    /**
     * Create a new SimpleTokeniser using a text and preset types and patterns
     * Note: The two lists have to be of the same length or the tokeniser will
     *       throw an exception
     * @param _text The text to tokenise
     * @param _tokenTypes The list of types
     * @param _tokenPatterns The list of Patterns
     * @throws UnbalancedTokenTypePatternListException If the types and patterns
     *         lists are not equal in length
     */
    public SimpleTokeniser(String _text, List<Integer> _tokenTypes, List<Pattern> _tokenPatterns) 
            throws UnbalancedTokenTypePatternListException {
        text = _text;
        tokenTypes = _tokenTypes;
        tokenPatterns = _tokenPatterns;
        if(tokenTypes.size() != tokenPatterns.size()) {
            throw new UnbalancedTokenTypePatternListException();
        }
        tokens = new ArrayList<>();
    }
    
    /**
     * Create a new SimpleTokeniser using a text
     * @param _text The text to tokenise
     */
    public SimpleTokeniser(String _text) {
        text = _text;
        tokenTypes =  new ArrayList<>();
        tokenPatterns = new ArrayList<>();
        tokens = new ArrayList<>();
    }
    
    /**
     * Add a new type-pattern pair to the lists
     * @param type The type (unique numerical identifier)
     * @param pattern The Pattern (from <code>Pattern.compile()</code>)
     */
    public void addTokenType(int type, Pattern pattern) {
        tokenTypes.add(type);
        tokenPatterns.add(pattern);
    }
    
    public void addTokenType(int type, String prePattern) {
        tokenTypes.add(type);
        tokenPatterns.add(Pattern.compile(prePattern));
    }
    
    /**
     * Get the current character
     * @return The character the index is currently pointing at
     */
    public String current() {
        return String.valueOf(text.charAt(index));
    }
    
    /**
     * Increment the index by one
     */
    public void next() {
        index++;
    }
    
    /**
     * Increment the index by <code>chars</code>
     * @param chars The number of times to increase it with
     */
    public void next(int chars) {
        index += chars;
    }
    
    /**
     * Decrement the index by one
     */
    public void prev() {
        index--;
    }
    
    /**
     * Decrement the index by <code>chars</code>
     * @param chars The number of times to decrement
     */
    public void prev(int chars) {
        index -= chars;
    }
    
    /**
     * Return a new Token for the String given by <code>current()</code>
     * @return The Token for the current character or a <code>new Token(-1, "" -1)</code>
     */
    public Token scanToken() {
        int i = 0;
        String character;
        while(i < tokenTypes.size()) {
            character = current();
            if(tokenPatterns.get(i).matcher(character).matches()) {
                Token thisToken = new Token(tokenTypes.get(i), character, index - skippedCharacters);
                tokens.add(thisToken);
                return thisToken;
            }
            i++;
        }
        skippedCharacters++;
        return new Token(-1, "", -1);
    }
    
    /**
     * Do <code>scanToken()</code> for every character in <code>text</code>
     * @return The list of tokens
     */
    public List<Token> tokenise() {
        while(index < text.length()) {
            scanToken();
            next();
        }
        return tokens;
    }
    
}
